package tcinert;



import com.siemens.icm.io.CommConnectionControlLinesListener;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import javax.microedition.io.CommConnection;
import tcinert.Stav;
import com.siemens.icm.io.ATCommandFailedException;
import com.siemens.icm.io.CommConnectionControlLines;
import java.io.InputStream;
import java.io.IOException;
import javax.microedition.io.Connector;

/**
 * Trida Jadro
 * - spousti hlavni program
 * @author Tomas Cinert
 */
public class Jadro implements Runnable{
    
    /* Aktualni cas pro log a pro zapis do DB*/
    Calendar datum;
    /* Seriova komunikace*/
    CommConnectionControlLines spojeni;
    CommConnectionControlLinesListener comListener;
    
    int c;
    private boolean loop=true;
    private boolean prijemDat=false;
    int i=0;
    // private int pocetChyb=0;
    /* Jednotlive tridy */
    Stav reset;
    Inicializace init;
    Spojeni spoj;
    Zaznam zaznam;
    Databaze databaze;
    Pripojeni pripojeni;
    //String a=null;
    /* Vlakna */
    Thread cteciVlakno;
    Thread uploadVlakno;
    /* Pomocne promenne */
    StringBuffer buffer;
    String[][]data;
    /**
     *Konstruktor
     * - inicializuje veskere tridy a spousti vlakna (cteni dat a upload dat)
     */
    public Jadro(Stav reset,Zaznam zaznam) {
        this.zaznam=zaznam;
        this.reset=reset;
        buffer=new StringBuffer();
        
        /* Program startuje */
        zaznam.zapis("Program startuje",typZapisu.Informativni);
        zaznam.zapis("Inicializace modemu",typZapisu.Informativni);
        
        /** Inicializace modemu */
        try {
            init=new Inicializace();
            init.setPin(1);         // Pokud incializace probehne v pohode, tak muzem jet dal
            zaznam.zapis("Inicializace modemu probehla v poradku",typZapisu.Informativni);
        } catch (IllegalStateException ex) {
            zaznam.zapis("Inicializace modemu"+ex.toString(),typZapisu.Chybovy);
            reset.setStav(true);
        } catch(ATCommandFailedException ex){
            zaznam.zapis("Inicializace modemu"+ex.toString(),typZapisu.Chybovy);
            reset.setStav(true);
        }catch (IOException ex){
            zaznam.zapis("1. Inicializace portu"+ex.toString(),typZapisu.Chybovy);
            try {
                init.inicializacePort(); // zkusit znovu zapnout, cist nejakej citac chyb a pokud ani podruhy se nepodari, tak vypnout a poslat sms, obe logovat
                init.setPin(1);         // Pokud inciializace v druhym kole probehne v pohode, tak muzem jet dal
            } catch (IOException ex2) {
                zaznam.zapis("2.Inicializace portu"+ex.toString(),typZapisu.Chybovy);
                // Vypnout, reportovat a jit dal a zkusit comak
            }
        }
        /* Seriove spojeni */
        serioveSpojeni();
        /* Test nacteni dat */
        vlaknoCteni();
        if(buffer==null) {
            zaznam.zapis("Nemame data. Spoustime cteni znova",typZapisu.Chybovy);
            init.reset();
            vlaknoCteni();
            if(buffer==null) {
                zaznam.zapis("Podruhe nebyly prijata data. Prepiname na komunikace po SPI",typZapisu.Chybovy);
                chybaKomunikace();
            }
            
        }
        zaznam.zapis("Inicializace serioveho spojeni probehla v poradku",typZapisu.Informativni);
        zaznam.zapis("Inicializace databaze",typZapisu.Informativni);
        /* Incializace databaze */
        databaze=new Databaze();
        try {
            if((data=databaze.odeslano())!=null) {
                init.nastaveniPripojeni();
                zaznam.zapis("Upload dat z predchazejiciho behu",typZapisu.Informativni);
                vlaknoUpload();
                if(data!=null) {
                    zaznam.zapis("Upload neprobehle, pokus o odeslani znovu",typZapisu.Chybovy);
                    vlaknoUpload();
                    if(data!=null) {
                        // Odlozit odeslani na dalsi pokus
                    } else {
                        zaznam.zapis("Data na podruhe odeslany",typZapisu.Informativni);
                    }
                } else {
                    zaznam.zapis("Data odeslany",typZapisu.Informativni);
                }
            }
            zaznam.zapis("Inicializace databaze probehla v poradku",typZapisu.Informativni);
        } catch (Exception ex) {
            zaznam.zapis("Problem s databazi. Odeslana sms technikovi",typZapisu.Chybovy);
        }
        serioveSpojeni();
        
       
    }
    /**
     *Metoda na otevreni serioveho spojeni
     * - synchronizovana
     **/
    private synchronized void serioveSpojeni() {
        zaznam.zapis("Inicializace serioveho spojeni",typZapisu.Informativni);
        try {
            spojeni = (CommConnectionControlLines) Connector.open("comm:COM0;baudrate=4800", Connector.READ_WRITE, true);
            comListener=new CommConnectionControlLinesListener(){
                public void DTRChanged(boolean SignalState) {
                    if(SignalState){
                        prijemDat=true;
                    } 
                    
                }
            };
            spojeni.addListener(comListener);
            zaznam.zapis("Otvirame seriove spojeni",typZapisu.Informativni);
            
        } catch (IOException ex) {
            zaznam.zapis("Nepodarilo se nam otevrit seriove spojeni",typZapisu.Chybovy);
        }
        
        
    }
    /**
     *Vytvori cteci vlakno 
     **/
    private synchronized void vlaknoCteni() {
        if(cteciVlakno!=null){
            cteciVlakno=null;
        }
        cteciVlakno=new Thread(new Spojeni(zaznam, buffer,spojeni));
        cteciVlakno.start();
    }
    /**
     *Vytvori vlakno na nahrani dat do vzdalene databaze
     *- uzavre seriove spojeni (bez toho nefunguje AT^SJNET)
     **/
     private synchronized  void vlaknoUpload() {
        uzavreniSpojeni();
        if(uploadVlakno!=null){
            uploadVlakno=null;
        }
        if(init.testSignalu()){     // Test registrace
            try {
                uploadVlakno=new Thread(new Pripojeni(zaznam,data));
            } catch (Exception ex) {
                zaznam.zapis("Upload se nezdaril:"+ex.toString(),typZapisu.Chybovy);
            }
            uploadVlakno.start();
            }
    }
    
     /**
      * Zavre seriove pripojeni
      **/
    private void uzavreniSpojeni() {
        try {
            spojeni.close();        // Musime uzavrit, jinak nejde GPRS
        } catch (IOException ex) {
            zaznam.zapis(ex.toString(),typZapisu.Chybovy);
        }        
    }
    
    /**
     * Pokud selhalo spojeni s deskou - nebyl poslan incializacni znak
     **/
    private void chybaKomunikace() {
        init.poslaniSMS("Selhalo spojeni s deskou"); 
        zaznam.zapis("Pokus uzavrit seriove spojeni a otevreni SPI spojeni",typZapisu.Informativni);
        try {
            spojeni.close();    // Pokus o uzavreni
        } catch (IOException ex) {
            zaznam.zapis("Uzavreni serioveho portu selhalo",typZapisu.Chybovy);
        }    
        otevreniSPI();      
    }
    
    
    
    /**
     *Metoda na inicializaci a otevreni SPI spojeni (alternativni komunikace)
     **/
    private void otevreniSPI() {
        init.otevritSPI();      // Dodelat AT listener na problem pri otevirani SPI
    }  // Udelat listener na AT^SPI .. chybu reportovat, domyslet tu chybu tam
    
    /**
     *Metoda na upravu dat prijatych
     **/
    public double upravaDat(int zacatek, int konec)
   {
       char[] pole = null;
       buffer.getChars(zacatek,konec,pole,0);
       return(Double.parseDouble((new String(pole))));
   }
    /**
     *Test zda na pad v datech
     **/
    public boolean testPadu()
    {
        if((buffer.charAt(16))=='A')
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    /**
     *Hlavni cast programu
     *- smycka, ktera obstarava beh programu
     **/
    public void run() {
        zaznam.zapis("Hlavni program nabiha", typZapisu.Informativni);
        while(loop){
            init.ATsend("AT+CFUN=9,0\r");       // USpani, cekani listenery
            i++;
            if(prijemDat)
            {
                vlaknoCteni();
                databaze.zapisDB(System.currentTimeMillis(),upravaDat(0,4),upravaDat(6,9),upravaDat(10,14),testPadu()); 
                prijemDat=false;
            }
            if(i==5) {
                
                reset.setStav(true);
                loop=false;
                
            }
            
            
            
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            
            
        }
    }
}